﻿/* Copyright 2007-2008 dnAnalytics Project.
 *
 * Contributors to this file:
 * Marcus Cuda
 *
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted provided that the following conditions are met:
 * 
 * * Redistributions of source code must retain the above copyright notice, this 
 *   list of conditions and the following disclaimer.
 * * Redistributions in binary form must reproduce the above copyright notice, 
 *   this list of conditions and the following disclaimer in the documentation
 *   and/or other materials provided with the distribution.
 * * Neither the name of the dnAnalytics Project nor the names of its contributors
 *   may be used to endorse or promote products derived from this software without
 *   specific prior written permission.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
using System.Collections;
using System.Collections.Generic;

namespace dnAnalytics.LinearAlgebra.IO.Matlab
{
    internal class MatlabFile
    {
        private readonly IDictionary<string, Matrix> _matrices = new ListDictionary<string, Matrix>();
        public string HeaderText { get; set; }
        public string FirstMatrixName { get; set; }

        public Matrix FirstMatrix
        {
            get
            {
                if (string.IsNullOrEmpty(FirstMatrixName) || !_matrices.ContainsKey(FirstMatrixName))
                {
                    return null;
                }
                return _matrices[FirstMatrixName];
            }
        }

        public IDictionary<string, Matrix> Matrices
        {
            get { return _matrices; }
        }
    }

    internal class ListDictionary<T, K> : IDictionary<T, K>
    {
        private readonly IList<T> _keys = new List<T>();
        private readonly IList<K> _values = new List<K>();

        #region IDictionary<T,K> Members

        public void Add(T key, K value)
        {
            _keys.Add(key);
            _values.Add(value);
        }

        public bool ContainsKey(T key)
        {
            return _keys.Contains(key);
        }

        public ICollection<T> Keys
        {
            get { return _keys; }
        }

        public bool Remove(T key)
        {
            if (_keys.Contains(key))
            {
                int pos = _keys.IndexOf(key);
                _values.RemoveAt(pos);
                _values.RemoveAt(pos);
                return true;
            }
            return false;
        }

        public bool TryGetValue(T key, out K value)
        {
            if (_keys.Contains(key))
            {
                value = _values[_keys.IndexOf(key)];
                return true;
            }
            value = default(K);
            return false;
        }

        public ICollection<K> Values
        {
            get { return _values; }
        }

        public K this[T key]
        {
            get
            {
                if (_keys.Contains(key))
                {
                    return _values[_keys.IndexOf(key)];
                }
                throw new KeyNotFoundException();
            }
            set
            {
                if (_keys.Contains(key))
                {
                    _values[_keys.IndexOf(key)] = value;
                }
                else
                {
                    Add(key, value);
                }
            }
        }

        public void Add(KeyValuePair<T, K> item)
        {
            Add(item.Key, item.Value);
        }

        public void Clear()
        {
            _keys.Clear();
            _values.Clear();
        }

        public bool Contains(KeyValuePair<T, K> item)
        {
            return _keys.Contains(item.Key) && _values[_keys.IndexOf(item.Key)].Equals(item.Value);
        }

        public void CopyTo(KeyValuePair<T, K>[] array, int arrayIndex)
        {
            for (int i = 0; i < _keys.Count; i++)
            {
                array[arrayIndex + i] = new KeyValuePair<T, K>(_keys[i], _values[i]);
            }
        }

        public int Count
        {
            get { return _keys.Count; }
        }

        public bool IsReadOnly
        {
            get { return false; }
        }

        public bool Remove(KeyValuePair<T, K> item)
        {
            if (Contains(item))
            {
                Remove(item.Key);
                return true;
            }
            return false;
        }

        public IEnumerator<KeyValuePair<T, K>> GetEnumerator()
        {
            for (int i = 0; i < _keys.Count; i++)
            {
                yield return new KeyValuePair<T, K>(_keys[i], _values[i]);
            }
        }

        IEnumerator IEnumerable.GetEnumerator()
        {
            return GetEnumerator();
        }

        #endregion
    }
}